#include <bits/stdc++.h>
using namespace std;


#ifdef oimasterkafuu
int startClock = clock();
#endif

typedef long long ll;
typedef long double ld;

ifstream fin("detect.in");
ofstream fout("detect.out");

const int MAXN = 100010;
const int MAXM = 100010;
const int MAXL = 1000010;

const int inf = 0x3f3f3f3f;

int n, m, L, V;

struct car {
    int d, v, a;
    int st, ed;
} a[MAXN];

int p[MAXM];

unordered_set<int> e[MAXM];
unordered_set<int> ep[MAXN];
unordered_set<int> que;
unordered_set<int> queP;

void solve() {
    fin >> n >> m >> L >> V;
    
    for (int i = 1; i <= n; ++i) {
        fin >> a[i].d >> a[i].v >> a[i].a;
    }

    for (int i = 1; i <= m; ++i) fin >> p[i];

    for (int i = 1; i <= n; ++i) {
        if (a[i].a == 0) {
            if (a[i].v <= V) {
                a[i].st = L + 1;
                a[i].ed = L + 1;
            }
            else {
                a[i].st = a[i].d;
                a[i].ed = L;
            }
        } else if (a[i].a > 0) {
            if (a[i].v > V) {
                a[i].st = a[i].d;
                a[i].ed = L;
            } else {
                ld addSpeedTime = (V - a[i].v) * 1.0 / a[i].a;
                ld position = a[i].v * addSpeedTime + 0.5 * a[i].a * addSpeedTime * addSpeedTime;
                position += a[i].d;
                if (position > L) {
                    a[i].st = L + 1;
                    a[i].ed = L + 1;
                } else {
                    a[i].st = ceil(position);
                    a[i].ed = L;
                }
            }
        } else if (a[i].a < 0) {
            if (a[i].v < V) {
                a[i].st = L + 1;
                a[i].ed = L + 1;
            } else {
                ld downSpeedTime = (a[i].v - V) * 1.0 / (-a[i].a);
                ld position = a[i].v * downSpeedTime + 0.5 * a[i].a * downSpeedTime * downSpeedTime;
                position += a[i].d;
                if (position > L + 1) {
                    a[i].st = a[i].d;
                    a[i].ed = L;
                } else {
                    a[i].st = a[i].d;
                    a[i].ed = floor(position);
                }
            }
        }
    }

    // #ifdef oimasterkafuu
    // for(int i = 1; i <= n; ++i) {
    //     cout << a[i].st << ' ' << a[i].ed << endl;
    // }
    // #endif

    for (int i = 1; i <= n; ++i) ep[i].clear();

    for (int i = 1; i <= m; ++i) {
        e[i].clear();
        for (int j = 1; j <= n; ++j) {
            if (p[i] >= a[j].st && p[i] <= a[j].ed) {
                e[i].insert(j);
                ep[j].insert(i);
            }
        }
    }

    int cnt = 0;

    queP.clear();

    for (int i = 1; i <= n; ++i) {
        if (!ep[i].empty()) {
            ++cnt;
            queP.insert(i);
        }
    }

    fout << cnt << ' ';

    cnt = 0;

    que.clear();

    for (int i = 1; i <= m; ++i) {
        if (e[i].empty()) ++cnt;
        else que.insert(i);
    }


    while (!queP.empty()) {
        bool flag = false;


        auto x = queP.begin();

        for (; x != queP.end(); ++x) {
            if (ep[*x].size() == 1) break;
        }

        
        if (x != queP.end()) {
            flag = true;

            int id = *(ep[*x].begin());
            que.erase(id);
            for(auto y : e[id]) {
                queP.erase(y);
                for (auto z : ep[y]) {if (z != id) e[z].erase(y);}
            }
        }

        if (flag) continue;


        auto minv = que.begin();
        for (auto i = que.begin(); i != que.end(); ++i) {
            if (e[*i].size() < e[*minv].size()) minv = i;
        }

        if(minv != que.end()) {
            ++cnt;
            for (auto x : e[*minv]) ep[x].erase(*minv);
            que.erase(minv);
        }
    }

    fout << cnt + que.size() << endl;
}

int main() {
    int t;
    fin >> t;
    while (t--) solve();

    #ifdef oimasterkafuu
    int endClock = clock();
    double clocks = (endClock - startClock) * 1000.0 / CLOCKS_PER_SEC;
    cout << fixed << setprecision(6) << clocks << "ms" << endl;
    #endif
}